/* jpegutil.c 

	JPEG utilities for (de)compression based on libjpeg

Contact: W. Gardner, wgardner@socs.uoguelph.ca
*/

#include <stdio.h>
#include <jpeglib.h>
#include "jpegutil.h"

unsigned char *readJPEG(FILE *file, int *height, int *width, int *bpp)
{	
	int i;
	unsigned long location = 0;	// in pixel buffer
	unsigned char *pixbuff = NULL;
	struct jpeg_error_mgr error;	// specifies error handler
	struct jpeg_decompress_struct image;	// decompression object
	JSAMPROW row[1];		// points to some row in pixbuff

	// specify error handling for image be done by the standard
	// error handler:
	//	initialize error struct
	//	make image.err point to that
	image.err = jpeg_std_error(&error);

	// initialize JPEG decompression object and specify image file
	jpeg_create_decompress(&image);
	jpeg_stdio_src(&image, file);

	// read in and interpret the image info:
	//	image_height,width; output_height,width; num_components
	// TRUE disallows a tables-only JPEG file
	jpeg_read_header(&image, TRUE);

	// prepare for looping on read_scanlines
	jpeg_start_decompress(&image);

	// return image dimensions to caller
	*height = image.image_height;
	*width = image.image_width;
	*bpp = image.num_components;

	// allocate pixel buffer for entire image
	pixbuff = malloc(image.output_width*image.output_height*image.num_components);
	if(pixbuff == NULL) return(NULL);

	// loop through scan lines (=rows)
	while(image.output_scanline < image.image_height)
	{
		// location in pixbuff of next row
		row[0] = &pixbuff[location];
		jpeg_read_scanlines(&image, row, 1);

		location += image.output_width * image.num_components;
	}

	// end the operation and cleanup the decompression object
	jpeg_finish_decompress(&image);
	jpeg_destroy_decompress(&image);

	// user must free pixel buffer
	return(pixbuff);
}

void writeJPEG(FILE *file, unsigned char *pic, int height, int width, int bpp)
{	
	struct jpeg_error_mgr error;
	struct jpeg_compress_struct image;
	JSAMPROW row[1];

	// same as readJPEG
	image.err = jpeg_std_error(&error);
	jpeg_create_compress(&image);
	jpeg_stdio_dest(&image, file);

	//set image properties
	image.in_color_space = JCS_RGB;	// assume this????
	image.input_components = bpp;
	image.image_height = height;	
	image.image_width = width;	
	jpeg_set_defaults(&image);

	// prepare for looping on write_scanlines
	jpeg_start_compress(&image, TRUE);
	
	// write image row by row
	while(image.next_scanline < image.image_height)
	{
		row[0] = &pic[image.image_width * image.next_scanline * image.input_components];
		jpeg_write_scanlines(&image, row, 1);
	}

	// same as readJPEG
	jpeg_finish_compress(&image);
	jpeg_destroy_compress(&image);
}
